/*
 * Unidata Platform Community Edition
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 * This file is part of the Unidata Platform Community Edition software.
 *
 * Unidata Platform Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Unidata Platform Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

package org.unidata.mdm.meta.service.segments;

import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.unidata.mdm.core.context.ModelChangeContext.ModelChangeType;
import org.unidata.mdm.core.service.MetaModelService;
import org.unidata.mdm.core.service.ModelIdentitySupport;
import org.unidata.mdm.draft.context.DraftPublishContext;
import org.unidata.mdm.draft.dto.DraftPublishResult;
import org.unidata.mdm.draft.type.Draft;
import org.unidata.mdm.draft.type.Edition;
import org.unidata.mdm.meta.context.UpsertDataModelContext;
import org.unidata.mdm.meta.module.MetaModule;
import org.unidata.mdm.meta.type.draft.ModelDraftConstants;
import org.unidata.mdm.meta.type.model.DataModel;
import org.unidata.mdm.system.type.pipeline.Finish;
import org.unidata.mdm.system.type.pipeline.Start;

/**
 * @author maria.chistyakova
 * @since  18.12.2019
 */
@Component(ModelDraftPublishFinishExecutor.SEGMENT_ID)
public class ModelDraftPublishFinishExecutor extends Finish<DraftPublishContext, DraftPublishResult> implements ModelIdentitySupport {
    /**
     * This segment ID.
     */
    public static final String SEGMENT_ID = MetaModule.MODULE_ID + "[MODEL_DRAFT_PUBLISH_FINISH]";
    /**
     * Localized message code.
     */
    public static final String SEGMENT_DESCRIPTION = MetaModule.MODULE_ID + ".model.draft.publish.finish.description";
    /**
     * MMS instance.
     */
    @Autowired
    private MetaModelService metaModelService;
    /**
     * Constructor.
     */
    public ModelDraftPublishFinishExecutor() {
        super(SEGMENT_ID, SEGMENT_DESCRIPTION, DraftPublishResult.class);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public DraftPublishResult finish(DraftPublishContext ctx) {
        DraftPublishResult result = new DraftPublishResult(publish(ctx));
        result.setDraft(ctx.currentDraft());
        return result;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean supports(Start<?, ?> start) {
        return DraftPublishContext.class.isAssignableFrom(start.getInputTypeClass());
    }

    protected boolean publish(DraftPublishContext ctx) {

        Draft draft = ctx.currentDraft();
        Edition edition = ctx.currentEdition();

        // If no data created by the draft just say it's ok
        if (Objects.nonNull(edition) && Objects.nonNull(edition.getContent())) {

            String storageId = draft.getVariables().valueGet(ModelDraftConstants.STORAGE_ID);
            Integer version = draft.getVariables().valueGet(ModelDraftConstants.DRAFT_START_VERSION);

            DataModel result = edition.getContent();

            UpsertDataModelContext uCtx = UpsertDataModelContext.builder()
                .entitiesGroupsUpdate(result.getEntitiesGroup())
                .entitiesUpdate(result.getEntities())
                .lookupEntitiesUpdate(result.getLookupEntities())
                .nestedEntitiesUpdate(result.getNestedEntities())
                .relationsUpdate(result.getRelations())
                .description(result.getDescription())
                .displayName(result.getDisplayName())
                .name(result.getName())
                .upsertType(ModelChangeType.FULL)
                .storageId(storageId)
                .version(version + 1)
                .force(ctx.isForce())
                .waitForFinish(true)
                .build();

            metaModelService.upsert(uCtx);
        }

        return true;
    }
}
